05. Abstract Factory

Abstract Factory

ND079 JPND C2 L03 A06 Abstract Factory V3

What is a Factory?

A factory is anything that creates objects. Factories are useful for hiding construction details from callers.

  • If the thing creating objects is a method, it's known as a factory method. You've already seen some examples of factory methods, such as Stream.of().
  • If the thing creating objects is also an object, it's known as an abstract factory. These are useful when you want to separate construction of objects into a completely separate Java interface.

When to Use Abstract Factories

  • You want to hide construction details from callers.
  • You want to encapsulate construction of several related objects into a single Java interface.

Abstract Factory Demo

ND079 JPND C2 L03 A07 Demo Abstract Factory

Code from Demo

PageParserFactory.java (interface)

package com.udacity.webcrawler.parser;

/**
 * A factory interface that supplies instances of {@link PageParser} that have common parameters
 * (such as the timeout and ignored words) preset from injected values.
 */
public interface PageParserFactory {

  /**
   * Returns a {@link PageParser} that parses the given {@link url}.
   */
  PageParser get(String url);
}

PageParserFactoryImpl.java

package com.udacity.webcrawler.parser;

import com.udacity.webcrawler.Timeout;
import com.udacity.webcrawler.profiler.Profiler;

import javax.inject.Inject;
import java.time.Duration;
import java.util.List;
import java.util.regex.Pattern;

/**
 * A {@link PageParserFactory} that wraps its returned instances using a {@link Profiler}.
 */
final class PageParserFactoryImpl implements PageParserFactory {
  private final Profiler profiler;
  private final List<Pattern> ignoredWords;
  private final Duration timeout;

  @Inject
  PageParserFactoryImpl(
      Profiler profiler, @IgnoredWords List<Pattern> ignoredWords, @Timeout Duration timeout) {
    this.profiler = profiler;
    this.ignoredWords = ignoredWords;
    this.timeout = timeout;
  }

  @Override
  public PageParser get(String url) {
    // Here, parse the page with the initial timeout (instead of just the time remaining), to make
    // the download less likely to fail. Deadline enforcement should happen at a higher level.
    PageParser delegate = new PageParserImpl(url, timeout, ignoredWords);
    return profiler.wrap(PageParser.class, delegate);
  }
}

Why are factories useful?

SOLUTION:
  • Factories can return different implementations of an interface, depending on how the factory is invoked.
  • Factories can create several related kinds of objects.
  • Allows you to delegate the construction of objects.

Which SOLID design principles apply to the abstract factory pattern?

SOLUTION:
  • Single Responsibility Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle